package com.smrtcold.dev.task;

import com.alibaba.fastjson.JSONObject;
import com.smrtcold.dev.dto.base.TempPressure;
import com.smrtcold.dev.dto.dev.base.Point;
import com.smrtcold.dev.dto.dev.base.XMZDevInfo;
import com.smrtcold.dev.dto.dev.task.BasGroup;
import com.smrtcold.dev.dto.dev.task.CompGroup;
import com.smrtcold.dev.dto.dev.task.CondenserGroup;
import com.smrtcold.dev.dto.dev.task.DevTask;
import com.smrtcold.dev.init.SystemInit;
import com.smrtcold.dev.mapper.DataMapper;
import com.smrtcold.dev.service.base.BaseServer;
import com.smrtcold.dev.utils.Utils;
import lombok.extern.log4j.Log4j2;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;


/**
 * 冷凝器调整
 */
@Log4j2
@Service
public abstract class BaseJob {


    @Value("${sys.apid}")
    protected String apid;

    @Autowired
    protected DataMapper dataMapper;
    @Autowired
    protected BaseServer baseServer;

    protected Long mid = 0L;
    protected Long taskid;
    protected int status = 0;

    protected  StringBuffer logContert ;
    //担心内存泄了，值变成共享--导致计算错误
//    protected   HashMap<String, Object> extParams=new  HashMap<>();
    //饱和压力计算缓存
    public static HashMap<String, Float> PRESSTEMPCACHE = new HashMap<>();


    protected void mainRun(DevTask task) {
        this.logContert=  new StringBuffer();
        this.taskid = task.getId();
        this.mid = task.getMid();
        try {
            boolean isallSuccess = this.run( task);
            status = isallSuccess ? 1 : 0;
            if (logContert.length() > 5) {
                this.baseServer.push(String.format("/%s/task/log/%s/%s", apid, mid, taskid), logContert.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
            status = 0;
            this.log( "任务执行失败：{}", e.getMessage());
            // 推送异常日志
            // push(String.format("HMI/%s/%s/log", apid, taskid), logContert.toString());
        }
        if (logContert.length() > 10) {
            this.dataMapper.addlog(taskid, status, 0, logContert.toString());
        }
    }

    public abstract boolean run( DevTask task) throws Exception;


    public void log( String fmt, Object... args) {
        if(args.length>0){
            fmt= String.format(fmt, args);
        }
        this.logContert.append(fmt);
        log.info(fmt);
    }

   /**
    * 读取参数
    * @param params
    * @return
    * @throws Exception
    */
    public HashMap<String, Object> initParams(HashMap<String, Object> params) throws Exception {
        HashMap<String, Object> data = new HashMap<>();
        for (String k : params.keySet()) {
            if (k.startsWith("pr_")) {
                Point p = JSONObject.parseObject(params.get(k).toString(), Point.class);
                String devid = p.getDevid();
                XMZDevInfo xmzDevInfo = SystemInit.get(devid);
                if (null != xmzDevInfo) {
                    Number number = xmzDevInfo.readPoint(p);
                    data.put(k, xmzDevInfo.readPoint(p));
                    data.put(k.substring(3), number);
                }
            }else if(k.startsWith("bs_")) {
                //表示批量读取
                Point p = JSONObject.parseObject(params.get(k).toString(), Point.class);
                String devid = p.getDevid();
                XMZDevInfo xmzDevInfo = SystemInit.get(devid);
                if (null != xmzDevInfo) {
                    String[] names = p.getName().split(",");
                    String[] split = p.getAddres().split(",");
                    List batch = xmzDevInfo.get(split);
                    for (int i = 0; i < split.length; i++) {
                        data.put( names[i], batch.get(i));
                        data.put(names[i]+"-devid",devid);
                        data.put(names[i]+"-addres",split[i]);
                    }
                    Double[] defvalue = p.getDefvalue();
                    //
                    if(null!=defvalue){
                        for (int i = 0; i < names.length; i++) {
                            data.put(names[i]+"-value",defvalue[i]);
                        }
                    }
                }
            }
            else {
                data.put(k, params.get(k));
            }
        }
        return data;
    }

    public long getRunCount(Point p,Map<String, Object> data) throws Exception {
        //获取压机运行状态
        XMZDevInfo xmzDevInfo = SystemInit.get(p.getDevid());
        String[] split = p.getAddres().split(",");
        String[] nams = p.getName().split(",");
        List<Number> vb = xmzDevInfo.get(split);
        for (int i = 0; i < vb.size(); i++) {
            data.put(split[i], vb.get(i));
            data.put(nams[i], vb.get(i));
        }
        return vb.stream().filter(Objects::nonNull).filter(i -> i.intValue() > 0).count();
    }

    public long getRunCount(String devid, String addres) throws Exception {
        //获取压机运行状态
        XMZDevInfo xmzDevInfo = SystemInit.get(devid);
        String[] split = addres.split(",");
        List<Number> vb = xmzDevInfo.get(split);
        return vb.stream().filter(Objects::nonNull).filter(i -> i.intValue() > 0).count();
    }

    public List getData(String devid, String addres) throws Exception {
        //获取压机运行状态
        XMZDevInfo xmzDevInfo = SystemInit.get(devid);
        String[] split = addres.replaceAll("@", ",").split(",");
        return xmzDevInfo.get(split);
    }


    public double getDouble(Map extParams, String key, Double... defvalue) {
        Object val =extParams.get(key);
        if (null != val) {
            return Double.parseDouble(val.toString());
        }
        return defvalue.length > 0 ? defvalue[0] : 0.0;
    }

    public float getFloat(Map extParams,  String key, Float... defvalue) {
        Object val = extParams.get(key);
        if (null != val) {
            return Float.parseFloat(val.toString());
        }
        return defvalue.length > 0 ? defvalue[0] : 0;
    }

    public int getInt( Map extParams,String key, int... defvalue) {
        Object val = extParams.get(key);
        if (null != val) {
            return Integer.parseInt(val.toString());
        }
        return defvalue.length > 0 ? defvalue[0] : 0;
    }

    public String getAddres( Map extParams,String key) {
        Object val = extParams.get(key);
        if (null != val) {
            return val.toString();
        }
        return null;
    }

    public boolean isRun( Map extParams) {
        Object val = extParams.get("回写控制");
        if (null != val) {
            return "1".equals( val.toString());
        }
        return false;
    }

    /**
     * 算法0：根据制冷剂和温度获取压力--线性
     *
     * @param refrigerant
     * @param temp
     * @return
     */
    protected float getlowMode0_Pressure(String refrigerant, float temp) {
        if (PRESSTEMPCACHE.containsKey(refrigerant + "_" + temp)) {
            return PRESSTEMPCACHE.get(refrigerant + "_" + temp);
        }

        Float lowPressure = this.dataMapper.getLowPressure(refrigerant, temp);
        if (null != lowPressure) {
            PRESSTEMPCACHE.put(refrigerant + "_" + temp, lowPressure);
            return lowPressure;
        }
        List<TempPressure> bounds = this.dataMapper.getxlLowPressure(refrigerant, temp);
        if (bounds.size() < 2) {
            // 只有一个边界点时直接返回
            float pressure = bounds.get(0).getPressure();
            PRESSTEMPCACHE.put(refrigerant + "_" + temp, pressure);
            return pressure;
        }

        // 3. 线性插值计算
        TempPressure lower = bounds.get(0), upper = bounds.get(1);
        double pressure = Math.round((
                lower.getPressure() +
                        (upper.getPressure() - lower.getPressure()) *
                                (temp - lower.getTemp()) /
                                (upper.getTemp() - lower.getTemp())
        ) * 100.0) / 100.0;  // 保留两位小数
        float n = (float) pressure;
        PRESSTEMPCACHE.put(refrigerant + "_" + temp, n);
        return n;
    }

    /**
     * 回写控制
     * @param newValue
     * @param oldvalue
     * @param
     * @return
     * @throws Exception
     */
    public boolean write( String devid,   String addres,String name, float newValue, float oldvalue,Float max,Float min) throws Exception {
        newValue = Float.parseFloat(Utils.DF.format(newValue));
        if (null!=max&& null!=min&&0.0!=max) {
            if (newValue > max) {
                newValue = max;
            } else if (newValue < min) {
                newValue = min;
            }
        }
        if (Utils.getDouble(oldvalue) == Utils.getDouble(newValue) && Math.abs(oldvalue - newValue) < 0.01) {
            log( "计算值与目标值一致：%s,%s",newValue, oldvalue);
            return true;
        }
        if(null==devid||null==addres){
            this.log("控制失败！参数不全！\r\n");
        }
        XMZDevInfo xmzDevInfo = SystemInit.get(devid);
        float oldNumber = xmzDevInfo.readAddres(addres).floatValue();
         xmzDevInfo.writeByAddres(addres, newValue);
        Thread.sleep(500);
        float number = xmzDevInfo.readAddres(addres).floatValue();
        log( "%s：%s-> %s,",name, oldNumber, newValue);
        if (number == newValue || Math.abs(number - newValue) < 0.01) {
            this.log( "成功！\r\n");
            return true;
        } else {
            this.log( "失败！\r\n");
            return false;
        }
    }


}
